<?php

class bobError extends Exception {
	public function __construct($message) {
		parent::__construct($message,null);
		return;
	}
}

class bob {

	static $config;
	static $configFile;
	static $configPath;
	static $configGlobal;
	static $configGlobalFile;
	static $configGlobalPath;
	static $cmd;

	static $server;

	static $run = 0;

	static $debug = false;

	static $splash = null;
	static $winReg = array();
	static $winIter = 0;
	
	static $fileIter = 0;	
	static $fileOpenLastDir;
	
	static $histSearch = array();
	static $histReplace = array();
	static $histFile = array();
	
	static $autocomp;
	static $langman;
	static $langlist;
	
	static function runUI() {
		while(Gtk::events_pending() || Gdk::events_pending()) {
			Gtk::main_iteration_do(true);
		} return;
	}
	
	static function keyMod($state,$mods) {
		if(($state & $mods) == $mods) {
			return true;
		} else {
			return false;
		}
	}
	
	static function debugfln($string) {
		if(self::$debug) {
			$arg = func_get_args();
			$arg[0] = strtolower(PROGRAM);
			
			vprintf("[%s-debug] {$string}\n",$arg);
		}
		
		return;
	}
	
	static function defaultSettings() {
		$defaultGlobal = array(
			'user-config' => 1
		);
		$default = array(
			'window-width' => 640,
			'window-height' => 480,
			'window-pos-x' => -1,
			'window-pos-y' => -1,
			'search-case' => 0,
			'search-from' => 0,
			'search-direction' => 1,
			'replace-type' => 1,
			'tab-width' => 5,
			'end-of-line' => 'LF',
			'font-main' => 'Bitstream Vera Sans Mono 8',
			'colour-current-line' => '#e8eeff',
			'colour-right-margin' => '#eaeaff',
			'pos-right-margin' => 80,
			'search-history' => new StdClass,
			'replace-history' => new StdClass,
			'file-history' => new StdClass
		);
		
		bob::debugfln('loading global config');
		bob::$configGlobalFile = bobConfigFile::mkFilePath(PROGRAM,$GLOBALS['PATH_CONFIG']);
		bob::$configGlobalPath = dirname(bob::$configGlobalFile);
		bob::$configGlobal = new bobConfigFile(bob::$configGlobalFile);
		bob::$configGlobal->setDefault(array_merge($defaultGlobal,$default),false);
		bob::$configGlobal->save();		
		
		if(bob::$configGlobal->get('user-config')) {
			bob::debugfln('loading user config');
			bob::$configFile = bobConfigFile::mkFilePath(PROGRAM);
			bob::$configPath = dirname(bob::$configFile);
			bob::$config = new bobConfigFile(bob::$configFile);
			bob::$config->setDefault($default,false);
		} else {
			bob::debugfln('user config disabled');
			bob::$configFile = bob::$configGlobalFile;
			bob::$config = bob::$configGlobal;
		}
		
		self::$histSearch = self::readHistoryObject('search-history');
		self::$histReplace = self::readHistoryObject('replace-history');
		self::$histFile = self::readHistoryObject('file-history');

		self::arrayShoveFront(self::$histFile,null);
		
		bob::$config->save();
	}
	
	static function readHistoryObject($which) {
		$obj = bob::$config->getGroup($which);
		$arr = array();

		if(!is_object($obj))
			return array();

		foreach($obj as $id => $value) {
			$arr[] = $value;
		} return $arr;
	}

	static function writeHistoryObject($which,$arr) {
		$obj = new StdClass;
		foreach($arr as $id => $value) {
			$id = preg_replace('/[^a-z0-9]/i','',"{$which}-{$id}");
			$obj->{$id} = $value;
		} return $obj;
	}
	
	static function arrayShoveFront(&$array,$what,$limit = 10) {
		if(is_array($array) && $what !== null) {
			if(($key = array_search($what,$array)) !== false) {
				unset($array[$key]);
				array_unshift($array,$what);
				$array = array_values($array);
			} else {
				array_unshift($array,$what);
			}
		}

		while(count($array) >= $limit) {
			array_pop($array);
		}
		
		return;
	}
	
	static function parseCommandLine() {
		$quit = false;
		$output = array(
			'file-open' => array()		
		);

		$arg = $_SERVER['argv'];
		for($a = 1; $a < count($arg); $a++) {
			switch($arg[$a]) {
				case('--new'): {
					bob::$config->set('force-server',1);
					break;
				}
				case('--version'): {
					printf(
						"%s v%s\n".
						"Released under The Revised BSD License\n".
						"Copyright (c) 2008 Bob Majdak Jr <bob@kateos.org>\n",
						PROGRAM,
						VERSION
					);
					$quit = true;
					break;
				}
				default: {
					$output['file-open'][] = $arg[$a];
					break;
				}
			}
		}
		
		if($quit) {
			exit(0);
		}
		
		return $output;
	}
	
	static function destroySplash() {
		if(method_exists(self::$splash,'set_opacity')) {
			Gtk::timeout_add(20,array(self::$splash,'runOpacity'),false,false);
			Gtk::main();
		}
		// ^ get the splash screen stuck owning the application while it
		// fades out

		self::$splash->hide();
		self::$splash->destroy();
		self::$splash = null;
		self::debugfln('splash screen destroyed');
		return;
	}
	
	static function destroyWindow($obj) {
		self::debugfln("window id {$obj->winIter} destroyed");
		$obj->hide();
		$obj->destroy();
		$obj = null;
		return;
	}
	
	static function endProgram() {
		if(Gtk::main_level()) {
			Gtk::main_quit();
		}

		bob::$config->delete('force-server');

		if(bob::$server)
			stream_socket_shutdown(bob::$server,STREAM_SHUT_RDWR);

		bob::$configGlobal->save();
		bob::$config->save();

		self::debugfln('computer, end program.');
		exit(0);
		return;
	}

	static function digRootUp($obj,$callback = null) {
		$org = $obj;
		$obj = $obj->get_parent();
		$class = null;

		while(is_object($obj) && ($class = get_class($obj)) != 'bobWindow') {
		//	echo("$class\n");
			$obj = $obj->get_parent();
		}
		
		//echo("$class\n");
		
		if($class == 'bobWindow') {
			$org->root = $obj;
			
			if(property_exists($org,'signalRoot') && is_numeric($org->signalRoot))
				$org->disconnect($org->signalRoot);

			$org->signalRoot = null;
			if($callback) {
				call_user_func($callback);
			}
		}
		
		return false;
	}
		
	/*//. int windowRegister(object window);
	  ../ register a window with the application so we can perform application
	  ../ instance wide operations on them later if needed.
	.//*/
	static function windowRegister($obj) {
		if(array_key_exists('winIter',$obj) && $obj->winIter >= 0) {
			throw new bobError('Specified window is already registered');
		}
		
		$obj->winIter = self::$winIter++;
		self::$winReg[$obj->winIter] = $obj;
		
		self::debugfln('new window registered: id %d',$obj->winIter);		
		
		return $obj->winIter;
	}

	/*//. void windowUnregister(object window);
	  ../ unregister this window before it is destroyed.
	.//*/	
	static function windowUnregister($obj) {
		if(!array_key_exists('winIter',$obj) || $obj->winIter < 0) {
			throw new bobError('Specified window is not registered');
		}
		
		unset(self::$winReg[$obj->winIter]);

		self::debugfln('window unregistered: %d',$obj->winIter);

		$obj->winIter = -1;
		return;
	}
	
	static function isLastWindow() {
		if(count(self::$winReg) === 1) {
			return true;
		} else {
			return false;
		}
	}
}

class bobSourceLanguageManager extends GtkSourceLanguagesManager {
	
	public function __construct() {
		parent::__construct();
		return;
	}
	
	public function get_language($mime) {
		$lang = $this->get_language_from_mime_type($mime);
		
		//. ending up moving the custom syntax colouring to the gtksourceview
		//. extended contructor.
				
		return $lang;
	}
}

?>